<template>
<div class="routeSimulate">
    <div class="full">
        <div class="toppanel">
            <div style="width: 5%;z-index: 99999999;display: flex;">
                <el-tooltip class="item" effect="dark" content="播放" placement="top">
                    <el-button type="text" style="font-size: 30px;margin-left: 2px;" v-show="!isPlay" @click="StartAnimation" circle>
                        <el-icon><VideoPlay /></el-icon>
                    </el-button>
                </el-tooltip>
                <el-tooltip class="item" effect="dark" content="暂停" placement="top">
                    <el-button type="text" style="font-size: 30px;" v-show="isPlay" @click="StopAnimation" circle>
                        <el-icon><VideoPause /></el-icon>
                    </el-button>
                </el-tooltip>
                <el-popover
                    placement="top"
                    width="200"
                    trigger="click">
                    <template #reference>
                        <el-button type="text" style="font-size: 30px;" @click="StopAnimation" circle>
                            <el-icon><Setting /></el-icon>
                        </el-button>
                    </template>
                    <template #default>
                        <span style="color:white;display:block;margin-bottom: 5px;">播放速度：</span>
                        <el-select v-model="StepCountEachTick" placeholder="请选择">
                            <el-option
                            v-for="item in playSpeed"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value">
                            </el-option>
                        </el-select>
                    </template>
                </el-popover>
            </div>
            <div style="width: 92%;padding-top:8px">
                <el-slider id="timeslider"
                    v-model="CurrentStep"
                    :min="0"
                    :max="GetTotalSteps()"
                    :format-tooltip="SliderValueChanged">
                </el-slider>
            </div>       
        </div>
      <div class="backpanel">
        <el-tooltip class="item" effect="dark" content="返回" placement="bottom">
          <el-button type="text" style="font-size: 30px;" @click="router.back()" circle>
            <el-icon><Back /></el-icon>
          </el-button>
        </el-tooltip>
      </div>
      <div class="godmapclass" id="GodMapPanel" ref="GodMapPanel"></div>
      <div class="uavmapclass" id="UavMapPanel" ref="UavMapPanel"></div>
    </div>
</div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElLoading } from 'element-plus'
import { VideoPlay, VideoPause, Setting, Back } from '@element-plus/icons-vue'
import { SimuFly, Tools } from '../assets/cesiumFunction/SmartView'
import { clearEntityLayer } from '../assets/cesiumFunction/Map'
import { v4 as uuidv4 } from 'uuid'
import { simulatedRouteLayerName } from '../assets/cesiumFunction/LayerName'
import * as Cesium from 'cesium'

/**
 * 显示3D立体多边形（基于 useAreaDrawing 的 show3DArea 方法）
 * @param {Object} viewer - Cesium viewer 实例
 * @param {String} areaId - 区域ID
 * @param {Array} positions - 位置数组（Cartesian3）
 * @param {String} layerName - 图层名称
 * @param {String} color - 颜色（CSS颜色字符串）
 */
const show3DArea = (viewer, areaId, positions, layerName, color = '#aed0ee') => {
    // 使用 Tools.AdjustManyHeight 调整高度，与无人机和航线保持一致
    const adjustedPositions = Tools.AdjustManyHeight(viewer, positions)
    
    const material = new Cesium.ColorMaterialProperty(
        Cesium.Color.fromCssColorString(color).withAlpha(0.5)
    )
    const outlineMaterial = new Cesium.PolylineDashMaterialProperty({
        dashLength: 16,
        color: Cesium.Color.fromCssColorString(color).withAlpha(0.7)
    })
    
    const outlinePositions = [].concat(adjustedPositions)
    outlinePositions.push(adjustedPositions[0])

    const entity = viewer.entities.add({
        layerId: layerName,
        objId: areaId,
        shapeType: "Polygon",
        polyline: {
            positions: outlinePositions,
            width: 2,
            material: outlineMaterial,
        },
        polygon: {
            hierarchy: adjustedPositions,
            perPositionHeight: true,  // 关键：启用每个点的高度
            asynchronous: false,
            material: material,
        }
    })
    
    return entity
}

/**
 * 显示3D立体线条（基于 useAreaDrawing 的 showLine 方法）
 * @param {Object} viewer - Cesium viewer 实例
 * @param {String} lineId - 线条ID
 * @param {Array} positions - 位置数组（Cartesian3）
 * @param {String} layerName - 图层名称
 * @param {String} color - 颜色（CSS颜色字符串）
 */
const show3DLine = (viewer, lineId, positions, layerName, color = '#aed0ee') => {
    // 使用 Tools.AdjustManyHeight 调整高度，与无人机和航线保持一致
    const adjustedPositions = Tools.AdjustManyHeight(viewer, positions)
    
    // 绘制3D线条
    const lineEntity = viewer.entities.add({
        layerId: layerName,
        objId: lineId,
        shapeType: "Polyline",
        polyline: {
            positions: adjustedPositions,
            width: 3,
            clampToGround: false,  // 不贴地，使用3D高度
            material: new Cesium.PolylineDashMaterialProperty({
                dashLength: 16,
                color: Cesium.Color.fromCssColorString(color).withAlpha(0.8)
            })
        }
    })
    
    return lineEntity
}

/**
 * 显示3D立体多边形（棱柱体）- 有顶面、底面和侧面
 * @param {Object} viewer - Cesium viewer 实例
 * @param {String} polyhedronId - 立体多边形ID
 * @param {Array} topPositions - 顶面位置数组（Cartesian3）
 * @param {String} layerName - 图层名称
 * @param {String} color - 颜色（CSS颜色字符串）
 */
const show3DPolyhedron = (viewer, polyhedronId, topPositions, layerName, color = '#aed0ee') => {
    // 使用 Tools.AdjustManyHeight 调整高度，与无人机和航线保持一致
    const adjustedTopPositions = Tools.AdjustManyHeight(viewer, topPositions)
    
    // 创建底面位置（高度设为0）
    const bottomPositions = adjustedTopPositions.map(pos => {
        const cartographic = Cesium.Cartographic.fromCartesian(pos)
        return Cesium.Cartesian3.fromRadians(
            cartographic.longitude,
            cartographic.latitude,
            0  // 底面高度为0
        )
    })
    
    const material = new Cesium.ColorMaterialProperty(
        Cesium.Color.fromCssColorString(color).withAlpha(0.5)
    )
    const outlineMaterial = new Cesium.PolylineDashMaterialProperty({
        dashLength: 16,
        color: Cesium.Color.fromCssColorString(color).withAlpha(0.7)
    })
    
    // 创建顶面多边形
    const topOutlinePositions = [].concat(adjustedTopPositions)
    topOutlinePositions.push(adjustedTopPositions[0])
    
    const topEntity = viewer.entities.add({
        layerId: layerName,
        objId: polyhedronId + '_top',
        shapeType: "Polygon",
        polyline: {
            positions: topOutlinePositions,
            width: 2,
            material: outlineMaterial,
        },
        polygon: {
            hierarchy: adjustedTopPositions,
            perPositionHeight: true,
            asynchronous: false,
            material: material,
        }
    })
    
    // 创建底面多边形
    const bottomOutlinePositions = [].concat(bottomPositions)
    bottomOutlinePositions.push(bottomPositions[0])
    
    const bottomEntity = viewer.entities.add({
        layerId: layerName,
        objId: polyhedronId + '_bottom',
        shapeType: "Polygon",
        polyline: {
            positions: bottomOutlinePositions,
            width: 2,
            material: outlineMaterial,
        },
        polygon: {
            hierarchy: bottomPositions,
            perPositionHeight: true,
            asynchronous: false,
            material: material,
        }
    })
    
    // 创建侧面（连接顶面和底面的每个对应点）
    adjustedTopPositions.forEach((topPos, index) => {
        const bottomPos = bottomPositions[index]
        const nextIndex = (index + 1) % adjustedTopPositions.length
        const nextTopPos = adjustedTopPositions[nextIndex]
        const nextBottomPos = bottomPositions[nextIndex]
        
        // 创建侧面四边形（两个三角形组成）
        const sidePositions = [
            topPos,
            nextTopPos,
            nextBottomPos,
            bottomPos
        ]
        
        viewer.entities.add({
            layerId: layerName,
            objId: polyhedronId + '_side_' + index,
            shapeType: "Polygon",
            polygon: {
                hierarchy: sidePositions,
                perPositionHeight: true,
                asynchronous: false,
                material: material,
            },
            polyline: {
                positions: sidePositions.concat([sidePositions[0]]),
                width: 1,
                material: outlineMaterial,
            }
        })
    })
    
    return { topEntity, bottomEntity }
}

const router = useRouter()
const route = useRoute()

let GodViewer = null         //上帝视角 
let UavViewer = null         //Uav视角
let simuFly = null           //飞行模拟

// 响应式数据
const isPlay = ref(false)  //是否播放动画
const CurrentStep = ref(0)
const StepCountEachTick = ref(1)
const loading = ref(null)
const flydata = ref([])
const playSpeed = ref([
    {
        value: 1,
        label: '一倍速'
    },
    {
        value: 2,
        label: '二倍速'
    },
    {
        value: 3,
        label: '三倍速'
    },
])

//const geoServiceUrl = ref("http://47.111.86.170:6005/geoserver")
const geoServiceUrl = ref("http://112.124.48.83/:6005/geoserver")


// 模板引用
const GodMapPanel = ref(null)

// 方法
const GetTotalSteps = () => {
    if (simuFly == null)
        return 0
    else
        return simuFly.GetTotal()
}

// 打开遮罩层功能
const loadingFuc = () => {
    loading.value = ElLoading.service({
        target: GodMapPanel.value,
        fullscreen: false,
        lock: true,
        text: '正在努力准备中..',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
    })
}

const SliderValueChanged = (step) => {
    if (simuFly != null) {
        simuFly.SetCurrentStep(step)
    }      
    return (step/10)+"秒"           
}

//该项操作可能耗时，最好能弹出对话框，提示: 数据准备中...
const Prepare = () => {
    loadingFuc()
    GodViewer.camera.setView({
        destination : Cesium.Cartesian3.fromDegrees(flydata.value[0].camera_lng, flydata.value[0].camera_lat, 5000.0),
    })
    simuFly.Prepare(flydata.value)
    simuFly.SetUavViewer()
    loading.value.close()
}

//可实时调整模拟速度，this.StepCountEachTick是绑定的v-model
const SpeedChange = () => {
    simuFly.SetStepCountEachTick(StepCountEachTick.value)
}

const StartAnimation = () => {
    isPlay.value = true
    var IntervalbetweenSteps = 100 //步长间的等待时间：毫秒，数字越小，速度越快
    var stepCountEachTick = StepCountEachTick.value      //每两个时间点间的步长：步数，数字越大，跳跃的越厉害
    var isLoop = false           //是否循环
    simuFly.StartAnimation(IntervalbetweenSteps, stepCountEachTick, isLoop)
}

const StopAnimation = () => {
    isPlay.value = false
    simuFly.StopAnimation()
    //如果希望删除画面中的实体，可调用
    //simuFly.RemoveEntities();
}

const processData = async () => {
    // 从路由参数获取数据
    let data
    if (typeof route.query.data === 'string') {
        data = JSON.parse(route.query.data)
    } else {
        data = route.query.data
    }
    
    let arr = []
    // 如果是沿线飞行的话没有actionGroup
    if (data.wayline_folder.template_type == 1) {
        data.display_wayline.fly_points.map((item, index) => {
            const element = {
                "camera_lng": item.uav_lng,
                "camera_lat": item.uav_lat,
                "camera_ground_height": item.uav_height,
                "camera_fieldofview": 55, //视野的zoom值
                "wait_time": 0,
                "speed": item.speed,
                "target_index": index,
                "sky_index": index,
                "platform_heading": item.uav_heading,
                "platform_pitch": item.platform_pitch,
                "aspect": 1.33, //TODO:先写成固定的
            }
            arr.push(element)
        })
        // 绘制区域多边形（立体）
        const objId = uuidv4()
        // 使用 Tools.GetCartesian3FromDegreesHeight 保持与无人机航线一致的高度处理方式
        let positions = data.wayline_folder.polygon.map(item => {
            return Tools.GetCartesian3FromDegreesHeight(item.longitude, item.latitude, item.altitude)
        })
        if (positions.length == 0) return
        const positionsInfo = positions.map(pos => {
            const cartographic = Cesium.Cartographic.fromCartesian(pos)
            return {
                longitude: Cesium.Math.toDegrees(cartographic.longitude),
                latitude: Cesium.Math.toDegrees(cartographic.latitude),
                height: cartographic.height
            }
        })
        console.log("positions 经纬度和高度:", positionsInfo)
        show3DArea(GodViewer, objId, positions, simulatedRouteLayerName, '#aed0ee')

    } else if (data.wayline_folder.template_type == 0) {
         data.display_wayline.fly_points.map((item, index) => {
            const element = {
                "camera_lng": item.uav_lng,
                "camera_lat": item.uav_lat,
                "camera_ground_height": item.uav_height,
                "camera_fieldofview": 55, //视野的zoom值
                "wait_time": 0,
                "speed": item.speed,
                "target_index": index,
                "sky_index": index,
                "platform_heading": item.uav_heading,
                "platform_pitch": item.platform_pitch,
                "aspect": 1.33, //TODO:先写成固定的
            }
            arr.push(element)
        })
    } else if (data.wayline_folder.template_type == 2) {
        data.display_wayline.fly_points.map((item, index) => {
            const element = {
                "camera_lng": item.uav_lng,
                "camera_lat": item.uav_lat,
                "camera_ground_height": item.uav_height,
                "camera_fieldofview": 55, //视野的zoom值
                "wait_time": 0,
                "speed": item.speed,
                "target_index": index,
                "sky_index": index,
                "platform_heading": item.uav_heading,
                "platform_pitch": item.platform_pitch,
                "aspect": 1.33, //TODO:先写成固定的
            }
            arr.push(element)
        })
        // 绘制区域多边形（立体）
        const objId = uuidv4()
        // 使用 Tools.GetCartesian3FromDegreesHeight 保持与无人机航线一致的高度处理方式
        let positions = data.wayline_folder.polygon.map(item => {
            return Tools.GetCartesian3FromDegreesHeight(item.longitude, item.latitude, item.altitude)
        })
        if (positions.length == 0) return
        show3DArea(GodViewer, objId, positions, simulatedRouteLayerName, '#aed0ee')
    }
    else if (data.wayline_folder.template_type == 3) {
        data.display_wayline.fly_points.map((item, index) => {
            const element = {
                "camera_lng": item.uav_lng,
                "camera_lat": item.uav_lat,
                "camera_ground_height": item.uav_height,
                "camera_fieldofview": 55, //视野的zoom值
                "wait_time": 0,
                "speed": item.speed,
                "target_index": index,
                "sky_index": index,
                "platform_heading": item.uav_heading,
                "platform_pitch": item.platform_pitch,
                "aspect": 1.33, //TODO:先写成固定的
            }
            arr.push(element)
        })
        // 绘制线条（立体）
        const objId = uuidv4()
        // 使用 Tools.GetCartesian3FromDegreesHeight 保持与无人机航线一致的高度处理方式
        let positions = data.wayline_folder.line_string.map(item => {
            return Tools.GetCartesian3FromDegreesHeight(item.longitude, item.latitude, item.altitude)
        })
        if (positions.length == 0) return
        show3DLine(GodViewer, objId, positions, simulatedRouteLayerName, '#aed0ee')
    }
    else if (data.wayline_folder.template_type == 4) {
        data.display_wayline.fly_points.map((item, index) => {
            const element = {
                "camera_lng": item.uav_lng,
                "camera_lat": item.uav_lat,
                "camera_ground_height": item.uav_height,
                "camera_fieldofview": 55, //视野的zoom值
                "wait_time": 0,
                "speed": item.speed,
                "target_index": index,
                "sky_index": index,
                "platform_heading": item.uav_heading,
                "platform_pitch": item.platform_pitch,
                "aspect": 1.33, //TODO:先写成固定的
            }
            arr.push(element)
        })
        // 绘制立体多边形（棱柱体）
        const objId = uuidv4()
        // 使用 Tools.GetCartesian3FromDegreesHeight 保持与无人机航线一致的高度处理方式
        let positions = data.wayline_folder.polygon.map(item => {
            return Tools.GetCartesian3FromDegreesHeight(item.longitude, item.latitude, item.altitude)
        })
        if (positions.length == 0) return
        show3DPolyhedron(GodViewer, objId, positions, simulatedRouteLayerName, '#aed0ee')
    }
    else {
        data.display_wayline.fly_points.map((item, index) => {
            const element = {
                "camera_lng": item.uav_lng,
                "camera_lat": item.uav_lat,
                "camera_ground_height": item.uav_height,
                "camera_fieldofview": 55, //视野的zoom值
                "wait_time": 0,
                "speed": item.speed,
                "target_index": index,
                "sky_index": index,
                "platform_heading": item.uav_heading,
                "platform_pitch": item.platform_pitch,
                "aspect": 1.33, //TODO:先写成固定的
            }
            arr.push(element)
        })
    }
    // arr[0].camera_fieldofview = 90
    //this.flydata = arr
    flydata.value = interpolatePath(arr)
}

//计算两点间距离（Haversine 公式）
const haversineDistance = (lat1, lon1, lat2, lon2) => {
    const R = 6371000 // 地球半径，单位：米
    const toRadians = Math.PI / 180

    const dLat = (lat2 - lat1) * toRadians
    const dLon = (lon2 - lon1) * toRadians
    const a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(lat1 * toRadians) *
        Math.cos(lat2 * toRadians) *
        Math.sin(dLon / 2) *
        Math.sin(dLon / 2)
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
    return R * c
}

//插值主函数
const interpolatePath = (arr) => {
    const interpolatedArr = []

    for (let i = 0; i < arr.length - 1; i++) {
        const p1 = arr[i]
        const p2 = arr[i + 1]

        // 使用平均速度或 p1.speed（假设是段速度）
        const speed = p1.speed // 单位：m/s
        if (speed <= 0) {
            console.warn("Speed is zero or negative, skipping segment", i)
            continue
        }

        // 计算两点间距离
        const distance = haversineDistance(
            p1.camera_lat,
            p1.camera_lng,
            p2.camera_lat,
            p2.camera_lng
        )

        // 计算飞行时间（秒）
        const duration = distance / speed // 单位：秒
        const numSteps = Math.floor(duration) // 每秒一个点，取整数秒

        // 把起始点加入（但避免重复）
        if (i === 0) {
            interpolatedArr.push({ ...p1, t: 0 }) // t 是相对时间
        }

        // 在 p1 到 p2 之间插值
        for (let step = 1; step <= numSteps; step++) {
            const t = step / numSteps // 插值比例 (0~1)

            const interpolatedPoint = {
                camera_lng: p1.camera_lng + t * (p2.camera_lng - p1.camera_lng),
                camera_lat: p1.camera_lat + t * (p2.camera_lat - p1.camera_lat),
                camera_ground_height: p1.camera_ground_height + t * (p2.camera_ground_height - p1.camera_ground_height),

                camera_fieldofview: p1.camera_fieldofview,
                wait_time: 0, // 假设飞行中无等待
                speed: p1.speed, // 可改为线性变化：p1.speed + t*(p2.speed - p1.speed)
                target_index: p1.target_index,
                sky_index: p1.sky_index,
                
                platform_heading: p1.platform_heading,
                platform_pitch: p1.platform_pitch,
                aspect: p1.aspect,
            }

            interpolatedArr.push(interpolatedPoint)
        }
    }

    // 添加最后一个点（如果前面没加）
    if (arr.length > 0) {
        const lastPoint = { ...arr[arr.length - 1] }
        interpolatedArr.push(lastPoint)
    }

    return interpolatedArr
}

//角度插值辅助函数（避免 359° -> 1° 的跳变）
const interpolateAngle = (a1, a2, t) => {
    const diff = a2 - a1
    const normalizedDiff = ((diff + 180) % 360) - 180 // 将差值归一化到 [-180, 180]
    return a1 + normalizedDiff * t
}

// 监听播放速度变化
watch(StepCountEachTick, () => {
    if (simuFly != null) {
        SpeedChange()
    }
})

onMounted(async () => {
    GodViewer = Tools.BuildViewer("GodMapPanel")
    UavViewer = Tools.BuildViewer("UavMapPanel")
    const terrainMapUrl = window.SystemConfig.terrainMapUrl
    let terrainMap = null
    if(terrainMapUrl !== ''){
        terrainMap = new Cesium.CesiumTerrainProvider({
            url: `${terrainMapUrl}`, // 地址记得换成自己的地形数据地址
            requestWaterMask: true, // 开启法向量
            requestVertexNormals: false, // 开启水面特效
        })
        GodViewer.terrainProvider = terrainMap
        UavViewer.terrainProvider = terrainMap
    }

    simuFly = new SimuFly(GodViewer, UavViewer, "UavMapPanel",
        "Model/UAV.glb", 90, "notarget", "relative", 100)
    
    //当无人机位置变化时，发出此事件，this.simuFly.CurrentTimeSpan记录的是航线当前时间秒数，假设开始是0秒
    window.addEventListener(simuFly.TimeChangeEventName, () => {
        CurrentStep.value = simuFly.GetCurrent()
    })
    //当完成数据加载工作时
    // window.addEventListener(simuFly.PrepareDoneEventName, () => {
    //     alert("完成数据准备工作！");
    // });
    await processData()
    Prepare()
})

onBeforeUnmount(() => {
    if (GodViewer) {
        clearEntityLayer(GodViewer, simulatedRouteLayerName)
    }
})
</script>

<style lang="scss" scoped>
.routeSimulate{
    position: relative;
    .el-button+.el-button {
        margin-left: 0px;
    }
}
.godmapclass{
      height: 100vh;
      width: 100vw;
      margin: 0;
      float:left;
      position: relative;
      overflow: hidden;
    }
    .backpanel{
      width: auto;
      margin: 0;
      position: fixed;
      top: 10px;
      left: 10px;
      z-index: 99;
      display: flex;
    }
    .uavmapclass{
      height: 300px;
      width: 30%;
      margin: 0;
    //   float:left;
      position: fixed;
      top: 80px;
      right:10px;
      z-index: 99;
      border:5px solid white;
      box-shadow: 5px 10px 5px 5px #0a0a0ac8;
    }
    .toppanel{
      width: 100%;
      margin: 0;
      position: fixed;
      bottom: 10px;
      z-index: 99;
      display: flex;
      
    }
    :deep(.el-popover__title){
        color: white;
    }
</style>

